use std::sync::Arc;

use axum::{extract::State, Json};
use validator::Validate;

use crate::{
    form,
    handler::{get_conn, log_error, AffResponse, Response},
    jwt::UserClaimsData,
    middleware::RequiredAuth,
    service, utils, AppState, Error, Result,
};

pub async fn index(
    State(_state): State<Arc<AppState>>,
    RequiredAuth(claims): RequiredAuth<UserClaimsData>,
) -> String {
    format!("logined user: {}", claims.data.email)
}

pub async fn change_password(
    State(state): State<Arc<AppState>>,
    RequiredAuth(claims): RequiredAuth<UserClaimsData>,
    Json(frm): Json<form::profile::ChangePassword>,
) -> Result<Json<Response<AffResponse>>> {
    let handler_name = "web/user/change_password";
    let pool = get_conn(&state);

    frm.validate()
        .map_err(Error::from)
        .map_err(log_error(handler_name))?;

    if &frm.new_password == &frm.password {
        return Err(Error::invalid_parameter("玩呢？新密码和现用密码一样"));
    }
    if &frm.new_password != &frm.re_password {
        return Err(Error::invalid_parameter("两次输入的密码不一致"));
    }

    let hashed_new_password =
        utils::password::hash(&frm.new_password).map_err(log_error(handler_name))?;

    let rows = service::user::change_password(
        &pool,
        &claims.data.id,
        &hashed_new_password,
        Some(&frm.password),
    )
    .await
    .map_err(log_error(handler_name))?;

    Ok(Response::ok(AffResponse { rows }).to_json())
}
